package editorsvg.editor.vista;

import editorsvg.geometria.MiDimension2D;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

/**
 * Implementación del conversor de cordenadas.
 * @author Jorge Berjano
 */
public class ConversorCoordenadas0 implements ConversorCoordenadas {
    
    private double zoom = 1;
    private Point2D origen = new Point2D.Double();    
    private AffineTransform transformacionAPixeles = new AffineTransform();    
    
    /** Constructor */
    public ConversorCoordenadas0() {
        
    }
    
     /**
     * Establece la proporción de escala de la vista actual.
     */       
    @Override
    public void setZoom(double zoom) {
        this.zoom = zoom;
    }
    
    /**
     * Obtiene la proporción de escala de la vista actual.
     */
    @Override
    public double getZoom() {
        return zoom;
    }
    /**
     * Acerca el punto de vista del documento en un factor determinado.
     * Si zoom es mayor que 1 acerca el punto de vista.
     * Si zoom es menor que 1 aleja el punto de vista.
     */
    @Override
    public boolean zoom(double zoom) {
        double nuevoZoom = this.zoom * zoom;
        if (nuevoZoom < 0.001 && nuevoZoom > 1000) {    
            return false;
        }
        this.zoom = nuevoZoom;
        return true;        
    }

    public Point2D getOrigen() {
        return origen;
    }

    @Override
    public void setOrigen(Point2D origen) {
        this.origen = origen;
    }    
    
    @Override
    public AffineTransform getAffineTransform() {
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.setToTranslation(origen.getX() * zoom, origen.getY() * zoom);
        affineTransform.scale(zoom, zoom);
        return affineTransform;
    }

    @Override
    public Shape transformarAPixeles(Shape shape) {
        transformacionAPixeles.setToIdentity();
        transformacionAPixeles.scale(zoom, zoom);
        transformacionAPixeles.translate(origen.getX(), origen.getY());
        return transformacionAPixeles.createTransformedShape(shape);
    }
    
    /**
     * Convierte un punto de unidades reales a pixeles segun la vista actual.
     */
    @Override
    public Point aPixeles(Point2D puntoReal) {
         
        int x = aPixeles(puntoReal.getX() + origen.getX());
        int y = aPixeles(puntoReal.getY() + origen.getY());
        
        return new Point(x, y);
    }
    
    /**
     * Convierte una dimension de unidades reales a pixeles segun la vista actual.
     */
    @Override
    public Dimension aPixeles(Dimension2D dimensionReal) {
        
        int ancho = aPixeles(dimensionReal.getWidth());
        int alto = aPixeles(dimensionReal.getHeight());
        
        return new Dimension(ancho, alto);
    }
    
    /**
     * Convierte un rectangulo de unidades reales a pixeles segun la vista actual.
     */
    @Override
    public Rectangle aPixeles(Rectangle2D retanguloReal) {
        
        int ancho = aPixeles(retanguloReal.getWidth());
        int alto = aPixeles(retanguloReal.getHeight());      
        int x = aPixeles(retanguloReal.getX() + origen.getX());
        int y = aPixeles(retanguloReal.getY() + origen.getY());
        
        return new Rectangle(x, y, ancho, alto);
    }
    
    /**
     * Convierte una medida de unidades reales a pixeles.
     */      
    @Override
    public int aPixeles(double medidaReal) {
        return (int) Math.round(medidaReal * zoom);
    }
    
    /**
     * Convierte una medida de pixeles a unidades reales.
     */   
    @Override
    public double aUnidadesReales(int medidaPixeles) {
        if (zoom == 0) {
            return 0;
        }
        return (double) medidaPixeles / zoom;
    }
    
    /**
     * Convierte un punto de pixeles a unidades reales.
     */
    @Override
    public Point2D.Double aUnidadesReales(Point puntoPixeles) {
                
        double x = aUnidadesReales(puntoPixeles.x) - origen.getX();
        double y = aUnidadesReales(puntoPixeles.y) - origen.getY();
  
        return new Point2D.Double(x, y);
    }
    
    /**
     * Convierte una dimension de pixeles a unidades reales.
     */
    @Override
    public Dimension2D aUnidadesReales(Dimension dimensionPixeles) {
       
        double ancho = aUnidadesReales(dimensionPixeles.width);
        double alto = aUnidadesReales(dimensionPixeles.height);
        
        return new MiDimension2D.Double(ancho, alto);
    }
    
    /**
     * Convierte un rectangulo de pixeles a unidades reales.
     */
    @Override
    public Rectangle2D aUnidadesReales(Rectangle rectanguloPixels) {
                
        double x = aUnidadesReales(rectanguloPixels.x) - origen.getX();
        double y = aUnidadesReales(rectanguloPixels.y) - origen.getY();
        
        double ancho = aUnidadesReales(rectanguloPixels.width);
        double alto = aUnidadesReales(rectanguloPixels.height);
        
        return new Rectangle2D.Double(x, y, ancho, alto);
    }
}
